package com.kandinfo.base.admin.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.kandinfo.base.admin.domain.ScheduleJob;
import com.kandinfo.base.admin.dto.ScheduleJobDto;
import com.kandinfo.base.admin.dto.ScheduleJobSearchDto;
import com.kandinfo.base.admin.repository.ScheduleJobJPARepository;
import com.kandinfo.base.admin.repository.ScheduleJobSearchRepository;
import com.kandinfo.base.admin.service.ScheduleJobService;
import com.kandinfo.base.admin.utils.QuartzJobFactory;
import com.kandinfo.base.admin.utils.QuartzJobFactoryDisallowConcurrentExecution;
import com.kandinfo.base.common.dto.ResultDto;
import com.kandinfo.base.common.dto.ResultDtoFactory;
import com.kandinfo.base.common.dto.widget.DataTablesResponseDto;
import com.kandinfo.base.common.service.AbstractService;

@Service
public class ScheduleJobServiceImpl extends AbstractService<ScheduleJob, Long, ScheduleJobJPARepository> implements ScheduleJobService {
    
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;
    
    @Autowired
    private ScheduleJobSearchRepository scheduleJobSearchRepository;
    
    @Autowired
    private ScheduleJobJPARepository scheduleJobJPARepository;
    
    @Resource
    public void setScheduleJobJPARepository(ScheduleJobJPARepository scheduleJobJPARepository) {
        super.setRepository(scheduleJobJPARepository);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
    public void addJob(ScheduleJob job) throws SchedulerException {
        if (job == null || !ScheduleJob.STATUS_RUNNING.equals(job.getJobStatus())) {
            return;
        }
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        // 不存在，创建一个
        if (null == trigger) {
            Class clazz = ScheduleJob.CONCURRENT_IS.equals(job.getIsConcurrent()) ? QuartzJobFactory.class : QuartzJobFactoryDisallowConcurrentExecution.class;

            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).build();

            jobDetail.getJobDataMap().put("scheduleJob", job);

            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

            trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } else {
            // Trigger已存在，那么更新相应的定时设置
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        }
    }
    
    @Override
    @Transactional
    public void deleteByPrimaryKey(List<Long> jobIds) {
        //scheduleJobSearchRepository.deletejob(jobIds);
        for (Long id : jobIds) {
        	scheduleJobJPARepository.deleteOne(id);
		}
        
    }

    @Override
    public void insert(ScheduleJob record) {
    	scheduleJobJPARepository.save(record);
       // scheduleJobSearchRepository.insertJob(record);
    }

    @Override
    public int insertSelective(ScheduleJob record) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public ScheduleJob selectByPrimaryKey(Long jobId) {
       // return scheduleJobSearchRepository.getJobById(jobId);
    	return scheduleJobJPARepository.findOne(jobId);
    }

    @Override
    public void updateByPrimaryKeySelective(ScheduleJob record) {
        
    }
    
    @Override
    public Integer addTask(ScheduleJob job) {
        //return scheduleJobSearchRepository.insertJob(job);
    	scheduleJobJPARepository.save(job);
    	return 1;
    }

    @Override
    public Integer updateByPrimaryKey(ScheduleJob record) {
    	scheduleJobJPARepository.saveAndFlush(record);
    	return 1;
//        Integer id = scheduleJobSearchRepository.updateById(record);
//        return id;
    }
    
    @Override
    public void changeStatus(Long jobId, String cmd) throws SchedulerException {
        ScheduleJob job = getTaskById(jobId);
        if (job == null) {
            return;
        }
        if ("stop".equals(cmd)) {
            deleteJob(job);
            job.setJobStatus(ScheduleJob.STATUS_NOT_RUNNING);
        } else if ("start".equals(cmd)) {
            job.setJobStatus(ScheduleJob.STATUS_RUNNING);
            addJob(job);
        }
        scheduleJobJPARepository.saveAndFlush(job);
        //scheduleJobSearchRepository.updateStatusByJobId(jobId, job.getJobStatus());;
    }
    
    /**
     * 从数据库中查询job
     */
    public ScheduleJob getTaskById(Long jobId) {
    	return scheduleJobJPARepository.findOne(jobId);
        //return scheduleJobSearchRepository.getJobById(jobId);
    }
    
    /**
     * 删除一个job
     * 
     * @param scheduleJob
     * @throws SchedulerException
     */
    @Override
    public void deleteJob(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.deleteJob(jobKey);

    }
    
    /**
     * 
    * Description: 暂停一个job
    *
    * @param scheduleJob
    * @throws SchedulerException
     */
    @Override
    public void pauseJob(Long jobId) throws SchedulerException {
        ScheduleJob scheduleJob = getTaskById(jobId);
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.pauseJob(jobKey);
        changeStatus(jobId,"2");
        //scheduleJobSearchRepository.updateStatusByJobId(jobId, "2");
    }
    
    /**
     * 
    * Description: 恢复一个job
    *
    * @param scheduleJob
    * @throws SchedulerException
     */
    @Override
    public void resumeJob(Long jobId) throws SchedulerException {
        ScheduleJob scheduleJob = getTaskById(jobId);
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.resumeJob(jobKey);
        changeStatus(jobId,"1");
        //scheduleJobSearchRepository.updateStatusByJobId(jobId, "1");
    }
    
    /**
     * 
    * Description: 立即执行job
    *
    * @param scheduleJob
    * @throws SchedulerException
     */
    @Override
    public void runAJobNow(Long jobId) throws SchedulerException{
        ScheduleJob scheduleJob = getTaskById(jobId);
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        scheduler.triggerJob(jobKey);
    }
    
    /**
     * 
    * Description: 更新job时间表达式
    *
    * @param scheduleJob
    * @throws SchedulerException
     */
    @Override
    public void updateJobCron(ScheduleJob scheduleJob) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 查询数据库中所有job信息
     */
    @Override
    public DataTablesResponseDto<ScheduleJobDto> getSearchByCon(ScheduleJobSearchDto searchDto) {
        DataTablesResponseDto<ScheduleJobDto> responseDtoList = new DataTablesResponseDto<ScheduleJobDto>();
        List<ScheduleJobDto> FeedbackDtoList = scheduleJobSearchRepository.searchByCon(searchDto);
        responseDtoList.setEcho(searchDto.getEcho());
        responseDtoList.setData(FeedbackDtoList);
        responseDtoList.setTotalDisplayRecords(scheduleJobSearchRepository
                .getScheduleJobListCount(searchDto));
        responseDtoList.setTotalRecords(scheduleJobSearchRepository
                .getScheduleJobListCount(searchDto));
        return responseDtoList;
    }
    
    @Override
    public ScheduleJob IsThere(ScheduleJob s) {
        return scheduleJobJPARepository.IsThere(s.getBeanClass(), s.getSpringId(), s.getMethodName());
    }
    
    @Transactional(value = "jpaTransactionManager")
    @Override
    public ResultDto deleteOne(Long id) {
    	ScheduleJob scheduleJob = selectByPrimaryKey(id);
    	try {
			deleteJob(scheduleJob);
		} catch (SchedulerException e) {
			LOGGER.error("", e);
			return ResultDtoFactory.toNack("删除失败！");
		}
        scheduleJobJPARepository.deleteOne(id);
        return ResultDtoFactory.toAck("删除成功！");
    }
    
    @Transactional(value = "jpaTransactionManager")
    @Override
    public ResultDto delete(String ids) {
        List<ScheduleJob> list = new ArrayList<ScheduleJob>();
        String[] strs = ids.split(",");
        for (int i = 0; i < strs.length; i++) {
            ScheduleJob s = selectByPrimaryKey(Long.parseLong(strs[i]));
            try {
    			deleteJob(s);
    		} catch (SchedulerException e) {
    			LOGGER.error("", e);
    			return ResultDtoFactory.toNack("删除失败！");
    		}
            list.add(s);
        }
        scheduleJobJPARepository.deleteInBatch(list);
        return ResultDtoFactory.toAck("删除成功！");
    }

	@Override
	public void InitJob() throws SchedulerException {
		List<ScheduleJob> list = scheduleJobJPARepository.findByStatus(1);
		for (ScheduleJob scheduleJob : list) {
			addJob(scheduleJob);
		}
	}
}
